package com.feizhaiyou.encrypt.handler;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import com.feizhaiyou.encrypt.annotation.Security;
import com.feizhaiyou.encrypt.codec.SecurityProcessor;
import com.feizhaiyou.encrypt.constants.SecurityMode;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import java.lang.annotation.Annotation;
import java.nio.charset.Charset;

/**
 * @author ls
 */
@Data
@Slf4j
public class CommonSecurityHandler implements SecurityHandler<Security> {

    private SecurityProcessor securityProcessor;

    private SecurityMode securityMode;

    private Charset charset = Charset.forName("UTF-8");

    public CommonSecurityHandler(SecurityProcessor securityProcessor, SecurityMode securityMode, String charsetName) {
        Assert.notNull(securityProcessor, "securityProcessor could not be null");
        this.securityProcessor = securityProcessor;
        this.securityMode = securityMode;
        if (charsetName != null && charsetName.length() > 0) {
            this.charset = Charset.forName(charsetName);
        }
    }


    @Override
    public Security acquire(Annotation[] annotations) {
        Security security = null;
        for (int i = 0; i < annotations.length; i++) {
            if (annotations[i] instanceof Security) {
                security = (Security) annotations[i];
                // 注解存在且required为true
                return security;
            }
        }
        return null;
    }

    @Override
    public String handleEncrypt(String source, Security annotation) {
        if (annotation.encrypt()) {
            try {
                byte[] encrypt = securityProcessor.encrypt(source.getBytes(this.charset));
                switch (securityMode) {
                    case BASE64:
                        return Base64Encoder.encode(encrypt);
                    case HEX:
                        return HexUtil.encodeHexStr(encrypt);
                    default:
                        break;
                }
            } catch (Exception e) {
                log.error("encrypt fail: {}, source field value: {}", e.getMessage(), source);
            }
        }
        return source;
    }

    @Override
    public String handleDecrypt(String source, Security annotation) {
        if (annotation.decrypt()) {
            try {
                byte[] decrypt = securityProcessor.decrypt(source);
                return StrUtil.str(decrypt, charset);
            } catch (Exception e) {
                log.error("decrypt fail: {}, source field value: {}", e.getMessage(), source);
            }
        }
        return source;
    }
}
